
import { isType, deepClone, dGet, findObjectKey } from './utils/index.js'

/**
 * 枚举类
 * @param {Object} enmuMap 枚举对象
 * 枚举格式：
 * {
 *    枚举key1: [枚举值2，枚举描述2],
 *    枚举key2: [枚举值2，枚举描述2]
 * }
 */
class Enum {
  /**
   * @param {Object} enmuMap 枚举map
   * @param {String} description 枚举描述
   */
  constructor (enmuMap = {}, description) {
    if (!isType(enmuMap, 'object')) {
      throw new TypeError('The argument should be an object！')
    }
    this._init(deepClone(enmuMap), description)
  }

  /**
   * 初始化
   * @param {Object} enmuMap 枚举对象
   * @param {String} description 描述
   * @private
   */
  _init (enmuMap, description) {
    this.__enmuMap__ = enmuMap
    this.description = description
    this._setProxy(enmuMap) //设置代理
  }

  /**
   * 设置代理
   * @param {Object} enmuMap
   * @private
   */
  _setProxy(enmuMap) {
    const keys = Object.keys(enmuMap)
    keys.forEach(key => {
      Object.defineProperty(this, key, {
        get: () => {
          return this.getVal(key)
        }
      })
    })
  }

  /**
   * 获取枚举值
   * @param {String} key 枚举KEY
   * @return {Number} 枚举值
   */
  getVal (key) {
    return dGet(this.__enmuMap__, [key, 0], null)
  }

  /**
   * 获取多个枚举值
   * @param {Array} paramN 多个枚举KEY
   * @return {Array} {[枚举key], 枚举值}
   */
  getValList (...args) {
    if (!Array.isArray(args) || !args.every(type => typeof type === 'string')) {
      return {}
    }
    return args.map(type => this.getVal(type))
  }

  /**
   * 获取多个枚举值Map
   * @param {Array} param 多个枚举KEY，如果不传递则返回所有
   * @return {Object} {[枚举key], 枚举值}
   */
  getValMap (...args) {
    if (Array.isArray(args) && !args.every(type => typeof type === 'string')) {
      return {}
    }
    const keys = Object.keys(this.__enmuMap__) // 不传递返回
    return keys.reduce((wrap, key) => {
      wrap[key] = this.getVal(key)
      return wrap
    }, {})
  }

  /**
   * 获取枚举名称
   * @param {String} key 枚举KEY
   * @return {String} 枚举名称
   */
  getName (key) {
    return dGet(this.__enmuMap__, [key, 1], null)
  }

  /**
   * 通过枚举值获取枚举名称
   * @param {String|Nunber} val
   * @return {String|Null}
   */
  getNameByValue (val) {
    if (!val) return null
    // 获取对象key
    return findObjectKey(this.__enmuMap__, valItm => valItm[0] === val, null)
  }

  /**
   * 获取枚举值名称
   * @param {String|Nunber} val
   * @return {String} name
   */
  getValName(val) {
    const enumItem = Object.values(this.__enmuMap__).find(v => v[0] === val)
    return enumItem ? enumItem[1] : ''
  }

  /**
   * 检测字段类型
   * @param {Number} typeVal 类型
   * @param {String} typeKey 类型key
   * @return {Boolean}
   */
  check (typeVal, typeKey) {
    return this.getVal(typeKey) === typeVal
  }
}

/**
 * 创建枚举
 * @param {Object} enumMap
 * @param {String} description
 * @returns
 */
const createEnum = (enumMap = {}, description="") => {
  var enumInstance = new Enum(enumMap, description) // 返回实例
  console.log(enumInstance)
  return enumInstance
}

// export
export { createEnum }
